package main

import "fmt"

/* 单例模式有三个要点：
1 某个类只能有一个实例
2 它必须自行创建这个实例
3 必须自行向整个系统提供这个实例
*/
/*
  保证一个类永远只有一个对象，这个对象还能被系统其他模块使用
*/

// 1.保证这个类非共有化，外界不能通过这个类直接创建一个对象
// 那么这个类就应该变得非共有访问 类名称首字母要小写

type singleton struct {
}

// 2 还要有一个指针可以指向这个唯一对象，但是这个指针永远不能改变方向
// go 中没有常指针的概念，所以只能通过将这个指针私有化不让外部模块访问
var instance *singleton = new(singleton)

// 3 如果全部都私有化，那么外部模块将永远无法访问到这个对象
// 所以需要对外部提供一个方法来获取到这个对象
// GetInstance 是否可以定义为singleton 一个成员方法？
// 答案是不能的，因为如果为成员方法就必须先访问对象、再访问函数
// 但是类和对象目前已经私有化、外界无法访问，所以这个方法一定是一个全局普通函数

func GetIntstance() *singleton {
	return instance
}

func (s *singleton) SomeThing() {
	fmt.Println("单例的某个方法")
}

func main() {
	s1 := GetIntstance()
	s1.SomeThing()

	s2 := GetIntstance()

	if s1 == s2 {
		fmt.Println("s1==s2")
	}
}
